#!/usr/bin/env python
# coding=utf8

import optparse
import os
import sys

pre_commit = """#!/usr/bin/env python
# coding=utf8

import re
import os
import sys
import commands


reg = r"#\s{0,}vhallEOF-.*-start\s*?\\n([\s\S]*?)\s*?#\s{0,}vhallEOF-.*-end"
suffix = '.pre-commit'


def filterBlankLine(content):
    return "\\n".join(
        filter(lambda c: c.strip() != "", content.split('\\n')))


def gitIgnoreAdd():
    gitIgnorePath = './.gitignore'
    if not os.path.isfile(gitIgnorePath):
        writeFile(gitIgnorePath, "*.pre-commit")
        return

    content = readFile(gitIgnorePath)
    mathchRes = re.search('\*' + suffix, content, re.M | re.I)
    if not mathchRes:
        content = filterBlankLine(content) + "\\n*" + suffix + "\\n"
        writeFile(gitIgnorePath, content)


def removePlaceholderCode(file):
    content = readFile(file)
    if not content:
        return False

    mathchList = re.findall(reg, content, re.M | re.I)

    newContent = content
    for item in mathchList:
        if item.strip():
            newContent = newContent.replace(item, "")

    if content != newContent:
        # 文件备份
        writeFile(file + suffix, content)

        writeFile(file, newContent)
        return True

    return False


def readFile(file):
    with open(file, mode='r') as fp:
        return fp.read()
    return ""


def writeFile(file, content):
    with open(file, mode='w') as fp:
        fp.write(content)


def gitAdd(changeFiles):
    for file in changeFiles:
        cmd = 'git add %s' % file
        os.system(cmd)


def getCommitFileCount():
    cmd = 'git diff --cached --name-status | wc -l'
    count = commands.getoutput(cmd)
    return int(count)


def getChangeFiles():
    changeFiles = list()
    cmd = '''git diff --cached --name-status | grep '.php$' | awk -F' ' '$1 !="D" && $1 !~/^R\d*/ {print $2}' | uniq'''

    files = commands.getoutput(cmd)
    if not files:
        return changeFiles

    for file in files.split('\\n'):
        isMatch = removePlaceholderCode(file)
        if isMatch:
            changeFiles.append(file)

    return changeFiles


def printChangedFiles(changeFiles):
    if changeFiles:
        print("----------- change file list -----------")
        for file in changeFiles:
            print("\033[32m" + file + "\033[0m")

        print("")


def recoveryFiles(changeFiles):
    for file in changeFiles:
        os.system("rm -f %s && mv %s%s %s" % (file, file, suffix, file))


def run():
    changeFiles = getChangeFiles()
    printChangedFiles(changeFiles)

    gitIgnoreAdd()
    gitAdd(changeFiles)

    count = getCommitFileCount()
    recoveryFiles(changeFiles)
    if count == 0:
        print("\033[31mcommit stop, nothing to commit, working tree clean\033[0m")
        sys.exit(1)
    sys.exit(0)


if __name__ == "__main__":
    run()

"""


def addGitPreCommitHookToComponent(vhallComponentDir):
    """
    向各组件的 .git/hook 中添加 pre_commit 的钩子文件
    """

    count = 0
    for comDir in os.listdir(vhallComponentDir):
        componentDir = os.path.join(vhallComponentDir, comDir)
        hookDir = os.path.join(componentDir, '.git/hooks')
        if not os.path.isdir(hookDir):
            cprint("文件夹不存在: %s" % hookDir)
            continue

        preCommitFilePath = os.path.join(hookDir, 'pre-commit')
        with open(preCommitFilePath, mode="w") as fp:
            fp.write(pre_commit)
            os.system("chmod 755 %s" % preCommitFilePath)

        cprint("[%s] add pre_commit success" % (componentDir))
        count += 1

    cprint("total add success count:" + str(count), True)


def delGitPreCommitHookFromComponent(vhallComponentDir):
    """
    删除 pre-commit 文件
    """
    count = 0
    for comDir in os.listdir(vhallComponentDir):
        componentDir = os.path.join(vhallComponentDir, comDir)
        hookDir = os.path.join(componentDir, '.git/hooks')
        preCommitFilePath = os.path.join(hookDir, 'pre-commit')

        if os.path.isfile(preCommitFilePath):
            os.remove(preCommitFilePath)
            cprint("[%s] deleted success" % preCommitFilePath)
            count += 1

    if count == 0:
        cprint("不存在可以删除的文件")
    else:
        cprint("total del success count:" + str(count), True)


def cprint(msg, flag=False):
    """
    带颜色的输出，
    flag:  false 为红色输出，true 为绿色输出
    """
    if flag:
        print("\033[32m"+msg+"\033[0m")
    else:
        print("\033[31m"+msg+"\033[0m")


def run(operator, vhallComponentDir):
    # vhallComponentDir = argv[1] if len(argv) > 1 else os.getcwd()
    baseDir = os.path.basename(vhallComponentDir)
    if baseDir != 'vhall-component':
        cprint("请输入组件(vhall-component)目录,或在该目录下执行命令")
        sys.exit(0)

    if not os.path.isdir(vhallComponentDir):
        cprint("组件目录(vhall-component)不存在:", vhallComponentDir)
        sys.exit(0)

    operatorMap = {
        "add": addGitPreCommitHookToComponent,
        "del": delGitPreCommitHookFromComponent
    }

    fn = operatorMap.get(operator)
    if fn:
        cprint("----------------%s pre-commit git hook--------------" %
               operator, True)
        fn(vhallComponentDir)


def main():
    usage = "python %prog -o/--opeartor <operator add or del> -d/--dir <vhall component dir>"
    parse = optparse.OptionParser(usage)
    parse.add_option("-o", "--operator", dest="operator",
                     type="string", default="add", help="opeartor type")
    parse.add_option("-d", "--dir", dest="dir", type="string",
                     default=".", help="vhall component dir")

    options, args = parse.parse_args()

    vhallComponentDir = options.dir or os.getcwd()
    run(options.operator, options.dir)


if __name__ == "__main__":
    main()
